package com.xwaf.platform.system.provider.serviceimpl.pay;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.gson.Gson;
import com.xwaf.platform.common.utils.http.IpUtil;
import com.xwaf.platform.system.api.entity.pay.wft.SwiftpassConfig;
import com.xwaf.platform.system.api.entity.pay.wft.WftMD5;
import com.xwaf.platform.system.api.entity.pay.wft.WftRequest;
import com.xwaf.platform.system.api.entity.pay.wft.WftSignUtils;
import com.xwaf.platform.system.api.entity.pay.wft.WftXmlUtils;
import com.xwaf.platform.system.api.service.pay.WftService;

public class WftServiceImpl implements WftService {
	private static Logger log = Logger.getLogger(WftServiceImpl.class);
	private final static String version = "2.0";
	private final static String charset = "UTF-8";
	private final static String sign_type = "WftMD5";

	@Autowired
	IpUtil ipUtil;

	/**
	 * 支付请求
	 */
	public Map<String, String> pay(HttpServletRequest req, HttpServletResponse resp, String openid, WftRequest wft)
			throws Exception {
		log.debug("支付请求...");
		// Demo 返回参数
		/**
		 * {<br>
		 * attach=附加信息,attach=附加信息 body=测试购买商品, charset=UTF-8,<br>
		 * is_raw=1, mch_create_ip=127.0.0.1,
		 * mch_id=101530270064,nonce_str=1528280517403,<br>
		 * notify_url=http://localhost:8080/jsapi_wx/testPayResult,<br>
		 * openid=osI5V4_5iON0KGUMode_g1Lqjqb8, out_trade_no=492723372263625,
		 * <br>
		 * service=pay.weixin.jspay, sign_type=WftMD5, total_fee=1, version=2.0
		 * <br>
		 * }
		 */
		SortedMap<String, String> map = WftXmlUtils.getParameterMap(req);
		map.put("out_trade_no", wft.getOut_trade_no());
		map.put("body", wft.getBody());
		map.put("total_fee", wft.getTotal_fee());
		// map.put("coupon_fee", wft.getCoupon_fee());

		log.info("req-map=" + map);
		map.put("service", "pay.weixin.jspay");// 接口类型：pay.weixin.jspay
		map.put("version", version);// 版本号，version默认值是2.0
		map.put("charset", charset);// 可选值 UTF-8 ，默认为 UTF-8
		map.put("sign_type", sign_type);// 签名类型，取值：WftMD5默认：WftMD5
		map.put("mch_id", SwiftpassConfig.mch_id); // 商户号，由平台分配
		map.put("is_raw", "1");// 值为1
		map.put("is_minipg", "1"); // 值为1，表示小程序支付；不传或值不为1，表示公众账号内支付
		map.put("notify_url", SwiftpassConfig.notify_url);
		map.put("nonce_str", String.valueOf(new Date().getTime()));

		// 用户openid sub_openid 是 String(128)
		// 微信用户关注商家公众号的openid（注：使用测试号时此参数置空，即不要传这个参数，使用正式商户号时才传入，参数名是sub_openid，具体请看文档最后注意事项第7点）
		map.put("openid", openid);

		map.put("mch_create_ip", ipUtil.getLocalHostLANAddress().getHostAddress());// 终端IP'
		Map<String, String> params = WftSignUtils.paraFilter(map);

		// 公众账号或小程序ID sub_appid 是 String(32)
		// 当发起公众号支付时，值是微信公众平台基本配置中的AppID(应用ID)；当发起小程序支付时，值是对应小程序的AppID

		StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
		WftSignUtils.buildPayParams(buf, params, false);
		String preStr = buf.toString();
		String sign = WftMD5.sign(preStr, "&key=" + SwiftpassConfig.key, "utf-8");
		map.put("sign", sign);

		String reqUrl = SwiftpassConfig.req_url;
		log.debug("reqUrl：" + reqUrl);

		log.debug("reqParams:" + WftXmlUtils.parseXML(map));
		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;
		String res = null;
		Map<String, String> resultMap = null;
		try {
			HttpPost httpPost = new HttpPost(reqUrl);
			StringEntity entityParams = new StringEntity(WftXmlUtils.parseXML(map), "utf-8");
			httpPost.setEntity(entityParams);
			httpPost.setHeader("Content-Type", "text/xml;utf-8");
			client = HttpClients.createDefault();
			response = client.execute(httpPost);
			if (response != null && response.getEntity() != null) {
				resultMap = WftXmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
				res = WftXmlUtils.toXml(resultMap);
				log.debug("请求结果：" + res);
				if (!WftSignUtils.checkParam(resultMap, SwiftpassConfig.key)) {
					res = "验证签名不通过";
				} else {
					if ("0".equals(resultMap.get("status")) && "0".equals(resultMap.get("result_code"))) {
						String pay_info = resultMap.get("pay_info");
						log.info("pay_info : " + pay_info);
						res = "ok";
					}
				}
			} else {
				res = "操作失败";
			}
		} catch (Exception e) {
			log.error("操作失败，原因：", e);
			res = "系统异常";
		} finally {
			if (response != null) {
				response.close();
			}
			if (client != null) {
				client.close();
			}
		}
		Map<String, String> result = new HashMap<String, String>();
		if ("ok".equals(res)) {
			resultMap.put("code", "1");
			result = resultMap;
		} else {
			resultMap.put("code", "2");
			result.put("status", "500");
			result.put("msg", res);
		}
		return resultMap;
	}

	/**
	 * 订单查询
	 */
	public void query(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		log.debug("订单查询...");
		SortedMap<String, String> map = WftXmlUtils.getParameterMap(req);

		map.put("service", "unified.trade.query");
		map.put("version", version);
		map.put("charset", charset);
		map.put("sign_type", sign_type);
		map.put("mch_id", SwiftpassConfig.mch_id);

		String key = SwiftpassConfig.key;
		String reqUrl = SwiftpassConfig.req_url;
		map.put("nonce_str", String.valueOf(new Date().getTime()));

		Map<String, String> params = WftSignUtils.paraFilter(map);
		StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
		WftSignUtils.buildPayParams(buf, params, false);
		String preStr = buf.toString();
		String sign = WftMD5.sign(preStr, "&key=" + key, "utf-8");
		map.put("sign", sign);

		log.debug("reqUrl:" + reqUrl);

		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;
		String res = null;
		try {
			HttpPost httpPost = new HttpPost(reqUrl);
			StringEntity entityParams = new StringEntity(WftXmlUtils.parseXML(map), "utf-8");
			httpPost.setEntity(entityParams);
			httpPost.setHeader("Content-Type", "text/xml;utf-8");
			client = HttpClients.createDefault();
			response = client.execute(httpPost);

			if (response != null && response.getEntity() != null) {
				Map<String, String> resultMap = WftXmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()),
						"utf-8");
				res = WftXmlUtils.toXml(resultMap);
				log.debug("请求结果：" + res);

				if (!WftSignUtils.checkParam(resultMap, key)) {
					res = "验证签名不通过";
				} else {
					if ("0".equals(resultMap.get("status"))) {
						if ("0".equals(resultMap.get("result_code"))) {
							log.debug("业务成功，在这里做相应的逻辑处理");
							String trade_state = resultMap.get("trade_state");
							log.debug("trade_state : " + trade_state);
							log.debug("这里商户需要同步自己的订单状态。。。");
						} else {
							log.debug("业务失败，尝试重新请求，并查看错误代码描叙");
						}
					} else {
						log.debug("这里是请求参数有问题...");
					}
				}
			} else {
				res = "操作失败!";
			}
		} catch (Exception e) {
			log.error("操作失败，原因：", e);
			res = "操作失败";
		} finally {
			if (response != null) {
				response.close();
			}
			if (client != null) {
				client.close();
			}
		}
		Map<String, String> result = new HashMap<String, String>();
		if (res.startsWith("<")) {
			result.put("status", "200");
			result.put("msg", "操作成功，请在日志文件中查看");
		} else {
			result.put("status", "500");
			result.put("msg", res);
		}
		resp.getWriter().write(new Gson().toJson(result));
	}

	/**
	 * 退款查询
	 */
	public void refundQuery(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		log.debug("退款查询...");
		SortedMap<String, String> map = WftXmlUtils.getParameterMap(req);

		map.put("service", "unified.trade.refundquery");
		map.put("version", version);
		map.put("charset", charset);
		map.put("sign_type", sign_type);

		String key = SwiftpassConfig.key;
		String reqUrl = SwiftpassConfig.req_url;
		map.put("mch_id", SwiftpassConfig.mch_id);
		map.put("nonce_str", String.valueOf(new Date().getTime()));

		Map<String, String> params = WftSignUtils.paraFilter(map);
		StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
		WftSignUtils.buildPayParams(buf, params, false);
		String preStr = buf.toString();
		String sign = WftMD5.sign(preStr, "&key=" + key, "utf-8");
		map.put("sign", sign);

		log.debug("reqUrl:" + reqUrl);

		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;
		String res = null;
		try {
			HttpPost httpPost = new HttpPost(reqUrl);
			StringEntity entityParams = new StringEntity(WftXmlUtils.parseXML(map), "utf-8");
			httpPost.setEntity(entityParams);
			httpPost.setHeader("Content-Type", "text/xml;utf-8");
			client = HttpClients.createDefault();
			response = client.execute(httpPost);
			if (response != null && response.getEntity() != null) {
				Map<String, String> resultMap = WftXmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()),
						"utf-8");
				res = WftXmlUtils.toXml(resultMap);
				log.debug("请求结果：" + res);

				if (!WftSignUtils.checkParam(resultMap, key)) {
					res = "验证签名不通过";
				}
			} else {
				res = "操作失败!";
			}
		} catch (Exception e) {
			log.error("操作失败，原因：", e);
			res = "操作失败";
		} finally {
			if (response != null) {
				response.close();
			}
			if (client != null) {
				client.close();
			}
		}
		Map<String, String> result = new HashMap<String, String>();
		if (res.startsWith("<")) {
			result.put("status", "200");
			result.put("msg", "操作成功，请在日志文件中查看");
		} else {
			result.put("status", "500");
			result.put("msg", res);
		}
		resp.getWriter().write(new Gson().toJson(result));
	}

	/**
	 * 退款
	 */
	public void refund(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		log.debug("退款...");
		SortedMap<String, String> map = WftXmlUtils.getParameterMap(req);

		map.put("service", "unified.trade.refund");
		map.put("version", version);
		map.put("charset", charset);
		map.put("sign_type", sign_type);

		String key = SwiftpassConfig.key;
		String reqUrl = SwiftpassConfig.req_url;
		map.put("mch_id", SwiftpassConfig.mch_id);
		map.put("op_user_id", SwiftpassConfig.mch_id);
		map.put("nonce_str", String.valueOf(new Date().getTime()));

		Map<String, String> params = WftSignUtils.paraFilter(map);
		StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
		WftSignUtils.buildPayParams(buf, params, false);
		String preStr = buf.toString();
		String sign = WftMD5.sign(preStr, "&key=" + key, "utf-8");
		map.put("sign", sign);

		log.debug("reqUrl:" + reqUrl);

		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;
		String res = null;
		try {
			HttpPost httpPost = new HttpPost(reqUrl);
			StringEntity entityParams = new StringEntity(WftXmlUtils.parseXML(map), "utf-8");
			httpPost.setEntity(entityParams);
			httpPost.setHeader("Content-Type", "text/xml;utf-8");
			client = HttpClients.createDefault();
			response = client.execute(httpPost);
			if (response != null && response.getEntity() != null) {
				Map<String, String> resultMap = WftXmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()),
						"utf-8");
				res = WftXmlUtils.toXml(resultMap);
				log.debug("请求结果：" + res);

				if (!WftSignUtils.checkParam(resultMap, key)) {
					res = "验证签名不通过";
				}
			} else {
				res = "操作失败!";
			}
		} catch (Exception e) {
			log.error("操作失败，原因：", e);
			res = "操作失败";
		} finally {
			if (response != null) {
				response.close();
			}
			if (client != null) {
				client.close();
			}
		}
		Map<String, String> result = new HashMap<String, String>();
		if (res.startsWith("<")) {
			result.put("status", "200");
			result.put("msg", "操作成功，请在日志文件中查看");
		} else {
			result.put("status", "500");
			result.put("msg", res);
		}
		resp.getWriter().write(new Gson().toJson(result));
	}
}
